<template>
  <div class="app-container">
    <el-button type="primary" @click="selectFiles">选择文件</el-button>
    <el-button
      v-if="this.fileList && this.fileList.length > 0"
      :disabled="uploading || uploadingItem"
      @click="startUpload"
      >全部开始</el-button
    >
    <el-button
      v-if="this.fileList && this.fileList.length > 0"
      :disabled="!(uploading || uploadingItem)"
      @click="pauseAll"
      >全部暂停</el-button
    >
    <el-button
      v-if="this.fileList && this.fileList.length > 0"
      @click="deleteAll"
      >全部取消</el-button
    >

    <el-table row-key="date" :data="fileList" style="width: 100%">
      <el-table-column label="文件名称" :show-overflow-tooltip="true">
        <template slot-scope="scope">
          <span>{{ scope.row.fileName }}</span>
        </template>
      </el-table-column>
      <el-table-column label="文件大小" width="200px">
        <template slot-scope="scope">
          <span>{{ scope.row.fileSize | formatSize }}</span>
        </template>
      </el-table-column>
      <el-table-column label="上传进度" width="300px">
        <template slot-scope="scope">
          <div class="custom-node">
            <el-progress
              style="display: inline-block"
              v-if="scope.row.amamComplete"
              :percentage="scope.row.curProgress"
              :stroke-width="20"
              status="success"
              :format="formatsuccess"
              :text-inside="true"
            ></el-progress>
            <el-progress
              style="display: inline-block"
              v-else-if="scope.row.amamError"
              :percentage="100"
              :stroke-width="20"
              status="exception"
              :format="format"
              :text-inside="true"
            ></el-progress>
            <el-progress
              style="display: inline-block"
              v-else
              :percentage="scope.row.curProgress"
              :stroke-width="20"
              :text-inside="true"
              :format="formatuploading"
            ></el-progress>
            <div>
              <div v-if="scope.row.amamError">
                <el-tooltip
                  placement="bottom"
                  class="tip-position"
                  popper-class="atooltip"
                  effect="dark"
                  content="请检查网络是否正常"
                >
                  <!-- <img src="/images/material/message.png" -->
                  /></el-tooltip
                >
              </div>
              <span v-else style="padding-left:20px"
                >{{ scope.row.curProgress }}%</span
              >
            </div>
          </div>
        </template>
      </el-table-column>
      <el-table-column fixed="right" label="操作" width="150">
        <template #default="scope">
          <el-button @click="startItem(scope.row)" type="text" size="small"
            >开始</el-button
          >
          <el-button @click="pauseItem(scope.row)" type="text" size="small"
            >暂停</el-button
          >
          <el-button @click="deleteItem(scope.row)" type="text" size="small"
            >取消</el-button
          >
        </template>
      </el-table-column>
    </el-table>

    <selector
      :showDialogUpload="showDialogUpload"
      :currentFileList="fileList"
      @close="closeUploadDialog"
      ref="materialselect"
    ></selector>
  </div>
</template>
<script>
import Vue from 'vue'
import FileMd5 from '@/utils/file-md5'
import SparkMD5 from 'spark-md5'
import Utils from '@/utils/utils'
import Resumable from '@/assets/js/resumable'
import Selector from './selector.vue'

window.SparkMD5 = SparkMD5

export default {
  name: 'Uploader',
  components: {
    Selector
  },
  data() {
    return {
      fileType: parseFloat(this.$route.query.fileType),
      resumable: null,
      totalPercent: 0,
      uploading: false,
      uploadingItem: false,
      fileList: [],
      showDialogUpload: false
    }
  },
  mounted() {
    this.uploading = false
    this.uploadingItem = false
    this.initUpload()
  },
  filters: {
    formatSize(value) {
      return Utils.formatBytes(value)
    },
    formatTime(value) {
      return Utils.formatDateTime(value)
    }
  },
  methods: {
    initUpload() {
      const self = this
      this.resumable = new Resumable({
        target: `${window.VUE_APP_API_SERVER_ADDRESS}/api/upload/chunk`,
        chunkSize: 1 * 1024 * 1024,
        simultaneousUploads: 1,
        testChunks: true,
        throttleProgressCallbacks: 1,
        method: 'octet',
        query: file => {
          const index = self.fileList.findIndex(
            x => x.uniqueIdentifier === file.uniqueIdentifier
          )
          const curFile = self.fileList[index]
          return {
            resumableFileHash: curFile.md5,
            resumableNodeId: 1,
            resumableUserName: this.$store.getters.user.username,
            resumableFileType: this.fileType,
            resumableModifyTime: curFile.modifyTime
          }
        },
        headers: {
          Authorization: `${this.$store.getters.token}`
        }
      })

      self.resumable.on('complete', () => {
        self.uploading = false
        self.uploadingItem = false
        if (this.resumable) {
          this.resumable.cancel()
        }
      })
      self.resumable.on('fileSuccess', file => {
        const index = self.fileList.findIndex(
          x => x.uniqueIdentifier === file.uniqueIdentifier
        )
        if (index !== -1) {
          const curFile = self.fileList[index]
          Vue.set(curFile, 'amamComplete', true)
        }
      })
      self.resumable.on('fileAdded', file => {
        file.successAdded = true
      })
      self.resumable.on('fileError', file => {
        const index = self.fileList.findIndex(
          x => x.uniqueIdentifier === file.uniqueIdentifier
        )
        if (index !== -1) {
          const curFile = self.fileList[index]
          Vue.set(curFile, 'amamError', true)
        }
      })
      self.resumable.on('fileProgress', file => {
        const index = self.fileList.findIndex(
          x => x.uniqueIdentifier === file.uniqueIdentifier
        )
        if (index !== -1) {
          const curFile = self.fileList[index]
          const progress = Math.floor(file.progress() * 100)
          if (curFile.curProgress !== progress) {
            Vue.set(curFile, 'curProgress', progress)
          }
        }
        self.totalPercent = Math.floor(self.resumable.progress() * 100)
      })
    },
    closeUploadDialog(ret) {
      this.showDialogUpload = false
      if (ret.ok) {
        this.fileList = [...this.fileList, ...ret.fileList]
      }
      if (this.uploading) {
        this.pauseAll()
        this.startUpload()
      }
    },
    startUpload() {
      const self = this
      const md5futures = []
      if (this.resumable) {
        this.resumable.cancel()
      }
      this.uploading = true
      this.fileList.forEach(f => {
        if (!f.md5) {
          const promise = new Promise(resolve => {
            Vue.set(f, 'hashing', true)
            FileMd5(f.file, (ok, md5) => {
              if (ok) {
                f.md5 = md5
              } else {
                Vue.set(f, 'md5Error', true)
              }
              Vue.set(f, 'hashing', false)
              resolve(true)
            })
          })
          md5futures.push(promise)
        }
      })
      Promise.all(md5futures).then(() => {
        self.fileList.forEach(f => {
          self.addItem(f)
        })
        setTimeout(() => self.resumable.upload(), 100)
      })
    },
    pauseAll() {
      this.resumable.pause()
      this.uploading = false
      this.uploadingItem = false
    },
    deleteAll() {
      this.$confirm(`确认取消上传${this.fileList.length}条数据?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.$message({
            type: 'success',
            message: '取消成功!'
          })
          this.uploading = false
          this.uploadingItem = false
          this.fileList = []
          if (this.resumable) {
            this.resumable.cancel()
          }
        })
        .catch(err => {
          console.log(err)
        })
    },
    startItem(f) {
      const self = this
      const md5futures = []
      if (this.resumable) {
        this.resumable.cancel()
      }
      this.uploadingItem = true
      this.fileList.forEach(f => {
        if (!f.md5) {
          const promise = new Promise(resolve => {
            Vue.set(f, 'hashing', true)
            FileMd5(f.file, (ok, md5) => {
              if (ok) {
                f.md5 = md5
              } else {
                Vue.set(f, 'md5Error', true)
              }
              Vue.set(f, 'hashing', false)
              resolve(true)
            })
          })
          md5futures.push(promise)
        }
      })
      Promise.all(md5futures).then(() => {
        const curIndex = self.fileList.findIndex(
          x => x.uniqueIdentifier === f.uniqueIdentifier
        )
        if (curIndex !== -1) {
          self.addItem(self.fileList[curIndex])
        }
        setTimeout(() => self.resumable.upload(), 100)
      })
    },
    pauseItem(data) {
      const fileIndex = this.resumable.files.findIndex(
        x => x.file.uniqueIdentifier === data.uniqueIdentifier
      )
      if (fileIndex !== -1) {
        if (this.resumable.files[fileIndex].isUploading()) {
          this.resumable.files[fileIndex].pause()
        }
      }
      if (!this.uploading) {
        this.uploadingItem = false
      }
    },
    deleteItem(data) {
      const fileIndex = this.resumable.files.findIndex(
        x => x.file.uniqueIdentifier === data.uniqueIdentifier
      )
      if (fileIndex !== -1) {
        if (this.resumable.files[fileIndex].isUploading()) {
          this.resumable.files[fileIndex].cancel()
        }
      }
      const curIndex = this.fileList.findIndex(
        x => x.uniqueIdentifier === data.uniqueIdentifier
      )
      if (curIndex !== -1) {
        this.fileList.splice(curIndex, 1)
      }
      if (this.uploadingItem) {
        this.uploadingItem = false
      }
      if (this.fileList.length === 0) {
        this.uploading = false
        this.uploadingItem = false
      }
    },
    addItem(f) {
      if (f.md5 && !f.amamComplete) {
        Vue.set(f, 'amamError', false)
        Vue.set(f, 'curProgress', 0)
        this.resumable.addFile(f.file, undefined)
      }
    },
    format() {
      return '上传出错'
    },
    formatsuccess() {
      return '上传完成'
    },
    formatuploading() {
      return ''
    },
    selectFiles() {
      this.$refs.materialselect.fileType = 'video'
      this.showDialogUpload = true
    }
  }
}
</script>
<style lang="scss" scoped>
//el-tree 文件夹图片与文字对齐
.custom-node {
  flex: 1;
  display: flex;
  align-items: center;
  font-size: 14px;
  padding-right: 8px;
}

/deep/ {
  .el-progress__text {
    font-size: 14px !important;
    padding-left: 8px;
  }
  .el-progress-bar__outer {
    background-color: #f4f4f5;
    width: 180px;
    border-radius: 0px;
  }
  .el-progress-bar__inner {
    border-radius: 0px;
    text-align: center;
  }
  .el-progress-bar__innerText {
    color: #ffffff;
  }
}
</style>
